home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource5 / 332_01 / charget.c < prev    next >
C/C++ Source or Header  |  1990-01-07  |  10KB  |  267 lines

  1. /****************************************************************/
  2. /* Getch() routines of the PCcurses package            */
  3. /*                                */
  4. /****************************************************************/
  5. /* This version of curses is based on ncurses, a curses version    */
  6. /* originally written by Pavel Curtis at Cornell University.    */
  7. /* I have made substantial changes to make it run on IBM PC's,    */
  8. /* and therefore consider myself free to make it public domain.    */
  9. /*                Bjorn Larsson (bl@infovox.se)    */
  10. /****************************************************************/
  11. /* 1.4:  Routines that ended in while-loops now end        */
  12. /*     with return(ERR) to avoid compiler warnings.        */
  13. /*     Use of short wherever possible. Portability        */
  14. /*     improvements:                    900114    */
  15. /* 1.3:     MSC -W3, Turbo'C' -w -w-pro checkes:        881005    */
  16. /* 1.2:     #undef:ine of getch now covers all the file, to    */
  17. /*     make sure this module's getch() calls go to DOS,    */
  18. /*     not to the PCCurses 'getch()' function. Fixed        */
  19. /*     thanks to N.D. Pentcheff:            881002    */
  20. /* 1.1:     Bug fixes: call to _curseskeytest() changed        */
  21. /*     _curseskeytst(). Test of that routine also        */
  22. /*     lacked () in one place:            870907    */
  23. /* 1.0:     Release:                    870515    */
  24. /****************************************************************/
  25.  
  26. #include <curses.h>
  27. #include <curspriv.h>
  28.  
  29. #undef getch                /* We use MSC getch() below */
  30. #undef ungetch
  31.  
  32. #include <conio.h>
  33.  
  34. static    short    rawgetch();        /* get raw char via BIOS */
  35. static    short    sysgetch();        /* get char via system */
  36. static    short    validchar();        /* keypad xlate and char check */
  37.  
  38. char _curses_charget_rcsid[] = "@(#)charget.c    v.1.4  - 900114";
  39.  
  40. static    short    buffer[_INBUFSIZ];    /* character buffer */
  41. static    short    pindex = 0;        /* putter index */
  42. static    short    gindex = 1;        /* getter index */
  43. static    WINDOW *w;            /* to reduce stack usage */
  44. static    short    ungind = 0;        /* wungetch() push index */
  45. static    short    ungch[NUNGETCH];    /* array of ungotten chars */
  46.  
  47. /* Table for key code translation of function keys in keypad mode */
  48. /* These values are for strict IBM keyboard compatibles only */
  49.  
  50. static    short    kptab[] =
  51.   {
  52.   0x3b,KEY_F(1),  0x3c,KEY_F(2),  0x3d,KEY_F(3),  0x3e,KEY_F(4),
  53.   0x3f,KEY_F(5),  0x40,KEY_F(6),  0x41,KEY_F(7),  0x42,KEY_F(8),
  54.   0x43,KEY_F(9),  0x44,KEY_F(10), 0x47,KEY_HOME,  0x48,KEY_UP,
  55.   0x49,KEY_PPAGE, 0x4b,KEY_LEFT,  0x4d,KEY_RIGHT, 0x4f,KEY_LL,
  56.   0x50,KEY_DOWN,  0x51,KEY_NPAGE, 0x52,KEY_IC,    0x53,KEY_DC,
  57.   0x54,KEY_F(11), 0x55,KEY_F(12), 0x56,KEY_F(13), 0x57,KEY_F(14),
  58.   0x58,KEY_F(15), 0x59,KEY_F(16), 0x5a,KEY_F(17), 0x5b,KEY_F(18),
  59.   0x5c,KEY_F(19), 0x5d,KEY_F(20), 0x5e,KEY_F(21), 0x5f,KEY_F(22),
  60.   0x60,KEY_F(23), 0x61,KEY_F(24), 0x62,KEY_F(25), 0x63,KEY_F(26),
  61.   0x64,KEY_F(27), 0x65,KEY_F(28), 0x66,KEY_F(29), 0x67,KEY_F(30),
  62.   0x73,KEY_LEFT,  0x74,KEY_RIGHT,  0x75,KEY_LL,   0x76,KEY_NPAGE,
  63.   0x77,KEY_HOME,  0x84,KEY_PPAGE,  0x100,        -1
  64.   };
  65.  
  66. /****************************************************************/
  67. /* Wgetch(win) gets a character from the terminal, in normal,    */
  68. /* cbreak or raw mode, optionally echoing to window  'win'.    */
  69. /****************************************************************/
  70.  
  71. int wgetch(win)
  72.   WINDOW    *win;
  73.   {
  74.   short    key;
  75.   short    cbr;
  76.  
  77.   if (ungind)                    /* if ungotten char exists */
  78.     return(ungch[--ungind]);            /* remove and return it */
  79.  
  80.   if ((!_cursvar.raw) && (!_cursvar.cbreak))    /* if normal */
  81.     if (gindex < pindex)            /* and data in buffer */
  82.       return(buffer[gindex++]);
  83.  
  84.   w = win;                    /* static for speed & stack */
  85.   pindex = 0;                    /* prepare to buffer data */
  86.   gindex = 0;
  87.   while(1)                    /* loop for any buffering */
  88.     {
  89.     if (_cursvar.raw)                /* get a raw character */
  90.       key = rawgetch();
  91.     else                    /* get a system character */
  92.       {
  93.       cbr = _cursesgcb();            /* get ^BREAK status */
  94.       _cursesscb(_cursvar.orgcbr);        /* if break return proper */
  95.       key = sysgetch();
  96.       _cursesscb(cbr);                /* restore as it was */
  97.       }
  98.     if (w->_nodelay && (key == -1))        /* if nodelay and no char */
  99.       return(-1);
  100.     if ((key == '\r') && _cursvar.autocr && !_cursvar.raw) /* translate cr */
  101.       key = '\n';
  102.     if (_cursvar.echo && (key < 0x100))        /* check if echo */
  103.       {
  104.       waddch(w,key);
  105.       wrefresh(w);
  106.       }
  107.     if (_cursvar.raw || _cursvar.cbreak)    /* if no buffering */
  108.       return(key);
  109.     if (pindex < _INBUFSIZ-2)            /* if no overflow, */
  110.       buffer[pindex++] = key;            /* put data in buffer */
  111.     if ((key == '\n') || (key == '\r'))        /* if we got a line */
  112.       return(buffer[gindex++]);
  113.     } /* while */
  114.   return (ERR);                    /* Can't happen */
  115.   } /* wgetch */
  116.  
  117. /****************************************************************/
  118. /* Flushinp() kills any pending input characters.        */
  119. /****************************************************************/
  120.  
  121. void flushinp()
  122.   {
  123.   while(_curseskeytst())        /* empty keyboard buffer */
  124.     _curseskey();
  125.   while(kbhit())            /* empty system's buffers */
  126.     (void) getch();
  127.   gindex = 1;                /* set indices to kill buffer */
  128.   pindex = 0;
  129.   ungind = 0;                /* clear ungch array */
  130.   } /* flushinp */
  131.  
  132. /****************************************************************/
  133. /* Wungetch() pushes back it's argument on the input stream. If    */
  134. /* OK, returns 1, otherwise returns 0.                */
  135. /****************************************************************/
  136.  
  137. int    wungetch(ch)
  138.   int     ch;
  139.   {
  140.   if (ungind >= NUNGETCH)        /* pushback stack full */
  141.     return(0);
  142.   ungch[ungind++] = ch;
  143.   return(1);
  144.   } /* wungetch() */
  145.  
  146. /****************************************************************/
  147. /* Mvgetch() first moves the stdscr cursor to a new location,    */
  148. /* then does a wgetch() on stdscr.                */
  149. /****************************************************************/
  150.  
  151. int    mvgetch(y,x)
  152.   int y;
  153.   int x;
  154.   {
  155.   wmove(stdscr,y,x);
  156.   return(wgetch(stdscr));
  157.   } /* mvgetch */
  158.  
  159. /****************************************************************/
  160. /* Mvwgetch() first moves the cursor of window 'win' to a new    */
  161. /* location, then does a wgetch() in 'win'.            */
  162. /****************************************************************/
  163.  
  164. int mvwgetch(win,y,x)
  165.   WINDOW *win;
  166.   int y;
  167.   int x;
  168.   {
  169.   wmove(win,y,x);
  170.   return(wgetch(win));
  171.   } /* mvwgetch */
  172.  
  173. /****************************************************************/
  174. /* rawgetch() gets a character without any interpretation at    */
  175. /* all and returns it. If keypad mode is active for the desig-    */
  176. /* nated window, function key translation will be performed.    */
  177. /* Otherwise, function keys are ignored.If nodelay mode is    */
  178. /* active in the window, then rawgetch() returns -1 if no cha-    */
  179. /* racter is available.                        */
  180. /****************************************************************/
  181.  
  182. static short rawgetch()
  183.   {
  184.   short    c;
  185.  
  186.   if (w->_nodelay && !_curseskeytst())
  187.     return(-1);
  188.   while(1)                      /* loop to get valid char */
  189.     {
  190.     if ((c = validchar(_curseskey())) >= 0)
  191.       return(c);
  192.     } /* while */
  193.   return (ERR);                    /* Can't happen */
  194.   } /* rawgetch */
  195.  
  196. /****************************************************************/
  197. /* Sysgetch() gets a character with normal ^S, ^Q, ^P and ^C    */
  198. /* interpretation and returns it. If keypad mode is active for    */
  199. /* the designated window, function key translation will be per-    */
  200. /* formed. Otherwise, function keys are ignored. If nodelay    */
  201. /* mode is active in the window, then sysgetch() returns -1 if    */
  202. /* no character is available.                    */
  203. /****************************************************************/
  204.  
  205. static short sysgetch()
  206.   {
  207.   short    c;
  208.  
  209.   if (w->_nodelay && !kbhit())
  210.     return(-1);
  211.   while(1)
  212.     {
  213.     c = getch();
  214.     if (c)                    /* if not a function key */
  215.       return(c & 0xff);                /* avoids sign-extending */
  216.     c = getch();
  217.     if ((c = validchar(c << 8)) >= 0)        /* get & check next char */
  218.       return(c);
  219.     } /* while */
  220.   return (ERR);                    /* Can't happen */
  221.   } /* sysgetch */
  222.  
  223. /****************************************************************/
  224. /* Validchar(c) chacks that 'c' is a valid character, and    */
  225. /* if so returns it, with function key translation applied if    */
  226. /* 'w' has keypad mode set. If char is invalid, returns -1.    */
  227. /****************************************************************/
  228.  
  229. static short validchar(c)
  230.   int    c;
  231.   {
  232.   short *scanp;
  233.  
  234.   if (c == 0x0300)            /* special case, ^@ = NULL */
  235.     return(0);
  236.   if (!(c & 0xff00))            /* normal character */
  237.     return(c);
  238.   if (!(w->_keypad))            /* skip f keys if not keypad mode */
  239.     return(-1);
  240.   c = (c >> 8) & 0xff;
  241.   scanp = kptab;
  242.   while(*scanp <= c)            /* search for value */
  243.     {                    /* (stops on table entry 0x100) */
  244.     if (*scanp++ == c)
  245.       return(*scanp);            /* found, return it */
  246.     scanp++;
  247.     }
  248.   return(-1);                /* not found, invalid */
  249.   } /* validchar */
  250.  
  251. /****************************************************************/
  252. /* _cursespendch() returns 1 if there is any character avai-    */
  253. /* lable, and 0 if there is none. This is not for programmer    */
  254. /* usage, but for the updatew routines.                */
  255. /****************************************************************/
  256.  
  257. bool    _cursespendch()
  258.   {
  259.   if (ungind)                /* ungotten char */
  260.     return(TRUE);
  261.   if (pindex > gindex)            /* buffered char */
  262.     return(TRUE);
  263.   if (_cursvar.raw)            /* raw mode test */
  264.     return(_curseskeytst());
  265.   return((bool)kbhit());        /* normal mode test */
  266.   } /* _cursespendch */
  267.